立即函式 IIFE (Immediately Invoked Function Expression),是可以立即執行的函式表達式,大部分情況下立即函式不需要定義名稱,以下為基本的立即函式:
// 具名函式的立即函式
(function fun() {
console.log('IIFE');
}());
// 匿名函式的立即函式
(function () {
console.log('IIFE');
}());
小括號位子也可移至最後,如下範例所示:
// 具名函式的立即函式
(function fun() {
console.log('IIFE');
})();
// 匿名函式的立即函式
(function () {
console.log('IIFE');
})();
而立即函式主要有以下特點:
立刻執行
立即函式不需要另外呼叫函式也可以立即執行
無法在函式外被再次執行
立即函式就算是具名函式,在函式外也無法被呼叫
(function fun() {
console.log('IIFE');
}());
// IIFE
fun(); // 錯誤訊息 - Uncaught ReferenceError: fun is not defined
立即函式式函式表達式
立即函式因為是表達式,會回傳值,所以可以將此值賦予到變數上
var callName = (function (nickName) {
return nickName;
}('Carol'));
console.log(callName); // Carol
因變數的作用域在函式內,所以可以透過立即函式限制變數的作用域
以下範例中,在立即函式內宣告 變數 nickName
,因變數的作用域在函式內,所以 變數 nickName
只能在此函式內被取得
(function () {
var nickName = 'Carol'
console.log(nickName);
}());
// Carol
console.log(nickName); // 錯誤訊息 - Uncaught ReferenceError: nickName is not defined
立即函式一般函式一樣可以傳遞參數
(function (nickName) {
console.log(nickName);
}('Carol'));
// Carol
雖然立即函式很常用來限制作用域,但有時常需要把立即函式裡的內容傳到另一個立即函式內,這時可以利用物件的傳參考特性,範例如下:
先宣告一個 變數 a
,此 變數 a
指向一個空的物件,讓 變數 a
為第一個立即函式的參數,則 參數 b
會與 變數 a
指向同一個物件參考路徑,所以就算增加物件內屬性,參數 b
與變數 a
的值還是相同
再讓 變數 a
為第二個立即函式的參數,參數 c
會與 變數 a
也會指向同一個物件參考路徑,所以可以看到在第一個立即函式中更改的內容
var a = {};
(function (b) {
b.nickName = 'Carol';
}(a));
(function (c) {
console.log(c.nickName);
}(a));
利用全域物件 window
,將全域物件傳入參數,此參數指向此物件的參考路徑,透過全域物件來傳遞值,此方法常會用在大型框架上(ex: Vue),用以確保框架可以正確掛載到全域變數上
(function (gobal) {
gobal.nickName = 'Carol';
}(window));
(function () {
console.log(nickName);
}());
在 Day10 - ASI 自動插入分號 中有提到,當新的一行是 (
開始,不會發生 ASI 規則,無法自動插入分號,所以若相鄰的 2 個立即函式沒有用分號分隔,會被視為同一行,造成錯誤
(function () {
}())
(function () {
}())
// 錯誤訊息 - Uncaught TypeError: (intermediate value)(...) is not a function
解決方法:
方法1:在立即函式後方加入分號
(function () {
}());
(function () {
}());
方法2:在立即函式前方加入分號
;(function () {
}())
;(function () {
}())